using System;
using System.Collections.Generic;
using UnityEngine;

public abstract partial class RoleEntity : MonoBehaviour
{
     
    private BattleController m_BattleContorller;
    public BattleController battleController
    {
        get
        {
            if (m_BattleContorller == null)
                m_BattleContorller = GetComponentInParent<BattleController>();
            return m_BattleContorller;
        }
    }

    
    public const float roleDefaultSpeed = 3f;

    [SerializeField]
    protected int m_PlayerId;
    public int playerId
    {
        get { return m_PlayerId; }
        set { m_PlayerId = value; }
    }
    protected int m_RoleId;
    public int roleId => m_RoleId;

    public int m_SkinIndex;
    public int skinIndex => m_SkinIndex;

    [SerializeField]
    protected float m_Speed = roleDefaultSpeed;
    public virtual float speed
    {
        get => m_Speed;
        set
        {
            m_Speed = value;
        }
    }

    /// <summary>
    /// orientation
    /// </summary>
    public Vector3 roleOrientation => transform.forward;

    /// <summary>
    /// action FSM
    /// </summary>
    protected PlayerActionFSM m_ActionFSMSystem;

    public PlayerActionFSM playerActionFSM => m_ActionFSMSystem;

    /// <summary>
    /// cur state
    /// </summary>
    public ActionState curAction => m_ActionFSMSystem?.curState as ActionState;


    /// <summary>
    /// real move vec
    /// </summary>
    protected Vector3 m_RealMoveVec;
    public Vector3 realMoveVec => m_RealMoveVec;

    /// <summary>
    /// ctrl move dir
    /// </summary>
    protected Vector3 m_CtrlMoveVec;

    public Vector3 ctrlMoveVec => m_CtrlMoveVec;
    /// <summary>
    /// current move speed
    /// </summary>
    protected float m_CurMoveSpeed;
    public float curMoveSpeed { get => m_CurMoveSpeed; set => m_CurMoveSpeed = value; }
    
    /// <summary>
    /// pos at pre frame
    /// </summary>
    private Vector3 m_PrePos;

    protected int m_Hp;
    public int hp => m_Hp;

    public int maxHp = 100;
    public bool dead => m_Hp <= 0;
    
    protected CapsuleCollider m_CapsuleCollider;
    public CapsuleCollider capsuleCollider
    {
        get
        {
            if(m_CapsuleCollider == null)
                m_CapsuleCollider = GetComponentInChildren<CapsuleCollider>();
            
            return m_CapsuleCollider;
        }
    }
    public string curActionStr;
    protected virtual void Awake()
    {
        m_Rigidbody = GetComponentInChildren<Rigidbody>();

        if (m_rc == null)
            m_rc = GetComponentInChildren<ZRoleAnim>();

        if (!m_RagdollCtrl)
            m_RagdollCtrl = gameObject.GetComponent<RagdollCtrl>();

        if(m_CapsuleCollider == null)
            m_CapsuleCollider = GetComponentInChildren<CapsuleCollider>();
        
        ShowNormalGo();

        m_Hp = maxHp;
        m_CurMoveSpeed = this.speed;
    }

    protected virtual void Start()
    {
        
    }

    public virtual void ReceiveDamage(int damage)
    {
        m_Hp -= damage;
    }

    public void SetMoveVec(Vector3 moveVec)
    {
        m_CtrlMoveVec = moveVec;
    }

    public virtual void StopMove()
    {
        GameDebug.Log($"{name} stop move");

        //m_MoveVec = Vector3.zero;
        m_CtrlMoveVec = Vector3.zero;

        this.Rigidbody.velocity = Vector3.zero;
    }
    

    public void InputActionSign(int sign)
    {
        m_ActionFSMSystem?.InputSign(sign);
    }
    
    
    ///<summary>
    /// die
    /// </summary>
    /// <param name="attacker"></param>
 
    public virtual void ReceiveDeadlyDamage()
    {
        m_Hp = 0;
        GameDebug.LogError($"{name} ReceiveDeadlyDamage");
    }  
    
    protected virtual void Update()
    {
        //Update FSM
        m_ActionFSMSystem?.Update(Time.deltaTime);
        
        if (Time.frameCount % 5 == 0)
        {
            Vector3 moveVector = transform.position - m_PrePos;

            if (moveVector.sqrMagnitude > 0.0000000000001f) 
            {
                this.m_RealMoveVec = moveVector;
            }
            else
            { 
                this.m_RealMoveVec = Vector3.zero;
            }  
               
            m_PrePos = transform.position;
        }
        curActionStr = curAction?.GetType().Name;
    }

    public const float c_rotateSpeed = 5;

    public static float DirToRotateAngle(Vector2 dir)
    {
        if (Mathf.Abs(dir.x) <= 0.0000001f)
        {
            return dir.y > 0 ? 0 : 180;
        }
        
        float angle = -180 * (Mathf.Atan(dir.y / dir.x)) / Mathf.PI + 90;
        if (dir.x < 0)
        {
            angle += 180;
        }
        else if (dir.y < 0)
        {
            angle += 360;
        }
        angle %= 360;
        return angle;
    }

    public float GetDistance(Vector3 pos)
    {
        var vec = transform.position - pos;
        vec.y = 0;
        return vec.magnitude;
    }

    protected virtual void FixedUpdate()
    {
        if (Rigidbody)
        {
            //GameDebug.Log($"{name} move:{m_MoveVec}");
            var vec = this.curMoveSpeed * this.ctrlMoveVec.normalized;
            vec.y = this.Rigidbody.velocity.y;
            this.Rigidbody.velocity = vec;
        }

    }

    protected virtual void LateUpdate()
    {
        this.ViewUpdate();
    }

    public override string ToString()
    {
        return $"[playerId:{playerId}  {name}]";
    }
}